import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class main extends JFrame implements ActionListener {
    JButton jButtons[] = new JButton[9];
    JButton jButton_computerFirst = new JButton("电脑先走");
    JButton jButton_playerFirst = new JButton("玩家先走");
    JButton jButton_replay = new JButton("重置游戏");
    JPanel jPanel_board, jPanel_sidebar;
    Font font = new Font(null, Font.PLAIN, 60);
    Game game;
    static int depth = 4;
    boolean playerTurn = false;
    private int[][] board = null;

    void init() {

        jPanel_board = new JPanel(new GridLayout(3, 3));
        jPanel_sidebar = new JPanel();

        jPanel_sidebar.setBackground(Color.lightGray);


        for (int i = 0; i < 9; i++) {
            jButtons[i] = new JButton("");
            jButtons[i].addActionListener(this);
            jButtons[i].setBackground(Color.white);
            jButtons[i].setBorder(BorderFactory.createLineBorder(Color.gray));
            jButtons[i].setFont(font);
            jPanel_board.add(jButtons[i]);
        }
        jPanel_sidebar.setLayout(new BoxLayout(jPanel_sidebar, BoxLayout.Y_AXIS));

        final JSlider jSlider = new JSlider(1, 9);
        jSlider.setLabelTable(jSlider.createStandardLabels(1));
        jSlider.setPaintLabels(true);
        jSlider.setValue(4);
        jSlider.setBorder(BorderFactory.createTitledBorder("搜索深度"));

        jPanel_sidebar.add(Box.createVerticalGlue());
        jPanel_sidebar.add(jSlider);
        jPanel_sidebar.add(Box.createVerticalStrut(10));
        jPanel_sidebar.add(jButton_computerFirst);
        jPanel_sidebar.add(Box.createVerticalStrut(10));
        jPanel_sidebar.add(jButton_playerFirst);
        jPanel_sidebar.add(Box.createVerticalStrut(10));
        jPanel_sidebar.add(jButton_replay);
        jPanel_sidebar.add(Box.createVerticalGlue());

        setLayout(new BorderLayout());
        add(jPanel_board, BorderLayout.CENTER);
        add(jPanel_sidebar, BorderLayout.EAST);

        jButton_computerFirst.addActionListener(this);
        jButton_playerFirst.addActionListener(this);
        jButton_replay.addActionListener(this);
        jSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                depth = jSlider.getValue();
            }
        });

    }

    main() {
        setTitle("一字棋");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(650, 480);
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        setLocation((screen.width - this.getWidth()) / 2, (screen.height - this.getHeight()) / 2);
        init();
        setVisible(true);
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        if (playerTurn) {
            for (int i = 0; i < 9; i++) {
                if (e.getSource() == jButtons[i]) {
                    playerTurn = false;
                    drawX(i);
                    //player first
                    if (game == null) {
                        int board[][] = getBoard();
                        game = new Game(board);
                        computerPlay();
                        playerTurn = true;
                        return;
                    }
                    //get currentNode
                    int pre_i = i / 3;
                    int pre_j = i % 3;
                    Node currentNode = game.currentNode.getNextNodeByPre(pre_i, pre_j);

                    game.setCurrentNode(currentNode);

                    if (game.currentNode.isWin()) {//MinNode
                        JOptionPane.showMessageDialog(this, "你赢了！");
                        return;
                    }
                    if (isFullOfChess()) {
                        JOptionPane.showMessageDialog(this, "平局！");
                        return;
                    }
                    //computer play
                    computerPlay();

                    if (game.currentNode.isWin()) {
                        JOptionPane.showMessageDialog(this, "你输了！");
                    } else if (isFullOfChess()) {
                        JOptionPane.showMessageDialog(this, "平局！");
                    } else playerTurn = true;
                    return;
                }
            }
        }

        if (e.getSource() == jButton_computerFirst) {
            playerTurn = false;
            resetBoard();
            jButton_computerFirst.setEnabled(false);
            jButton_playerFirst.setEnabled(false);

            game = new Game(getBoard());
            computerPlay();
            playerTurn = true;
        } else if (e.getSource() == jButton_playerFirst) {
            playerTurn = true;
            jButton_computerFirst.setEnabled(false);
            jButton_playerFirst.setEnabled(false);
        } else if (e.getSource() == jButton_replay) {
            reset();
        }
    }

    boolean isOneWin(int board[][]) {
        //row
        for (int i = 0; i < 3; i++) {
            if (board[i][0] != 0 && board[i][0] == board[i][1] && board[i][0] == board[i][2]) {

                return true;
            }
        }
        //column
        for (int i = 0; i < 3; i++) {
            if (board[0][i] != 0 && board[0][i] == board[1][i] && board[0][i] == board[2][i]) {
                return true;
            }
        }
        //diagonal
        if (board[0][0] != 0 && board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
            return true;
        }
        if (board[2][0] != 0 && board[2][0] == board[1][1] && board[2][0] == board[0][2]) {
            return true;
        }
        return false;
    }


    private void reset() {
        // TODO Auto-generated method stub
        playerTurn = false;
        resetBoard();
        jButton_computerFirst.setEnabled(true);
        jButton_playerFirst.setEnabled(true);
        game = null;
    }

    void resetBoard() {
        for (int i = 0; i < 9; i++) {
            jButtons[i].setText("");
            jButtons[i].setEnabled(true);
        }
    }

    void drawO(int i) {
        jButtons[i].setText("O");
        jButtons[i].setEnabled(false);
    }

    void drawX(int i) {
        jButtons[i].setText("X");
        jButtons[i].setEnabled(false);
    }

    int[][] getBoard() {
        int board[][] = new int[3][3];
        for (int i = 0; i < 9; i++) {
            int m = i / 3, n = i % 3;
            String string = jButtons[i].getText();
            if (string.equals("")) {
                board[m][n] = 0;
            } else if (string.equals("X")) {//player
                board[m][n] = 1;
            } else if (string.equals("O")) {//computer
                board[m][n] = -1;
            }
        }
        return board;
    }

    void computerPlay() {
        Node currentNode = game.getCurrentNode();
        currentNode.play(depth, Game.UNKNOWN_INT, Game.UNKNOWN_INT);
        currentNode = currentNode.getNextNode();
        if (currentNode != null) {
            drawO(3 * currentNode.pre_i + currentNode.pre_j);
        }
        game.setCurrentNode(currentNode);
    }

    boolean isFullOfChess() {
        for (int i = 0; i < 9; i++) {
            if (jButtons[i].getText().equals("")) return false;
        }
        return true;
    }

    public static void main(String[] args) {
        new main();
    }
}
